package spring.cloud.tasks.tasks_manager.tasks_manager.task_item_allot.executor;

import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import spring.cloud.tasks.tasks_manager.tasks_manager.service.AllotTaskItemService;
import spring.cloud.tasks.tasks_manager.tasks_manager.task_item_allot.TaskItemAllotTask;
import spring.cloud.tasks.tasks_manager.tasks_manager.task_item_allot.task.TaskItem;

import java.util.Iterator;
import java.util.List;

/**
 * 摘取executor流量，标记该executor的noTraffic为true，并移除其所有作业分片，只摘取所有非本地作业分片，设置totalLoadLevel为0
 */
@Slf4j
@Setter
@Getter
public class ExecutorLostTrafficTaskItemAllotTask extends TaskItemAllotTask {

    private String executorId;

    public ExecutorLostTrafficTaskItemAllotTask(AllotTaskItemService allotTaskItemService, String executorId) {
        super(allotTaskItemService);
        this.allotTaskItemService = allotTaskItemService;
        this.executorId = executorId;
    }

    @Override
    protected void logStartInfo() {
        log.info("Execute the {} with {} extract traffic", this.getClass().getSimpleName(), executorId);
    }

    /**
     * 失去流量但是不下线
     *
     * @param taskIdList                   该域下所有作业
     * @param enableTaskIdList             该域下所有启用的作业
     * @param taskItemList                 默认为空集合
     * @param onlineExecutorList           默认为当前存储的数据，如果不想使用存储数据，请重写{@link #customLastOnlineExecutorList()}}方法
     * @param onlineOwnTrafficExecutorList lastOnlineExecutorList中所有noTraffic为false的Executor，注意Executor是同一个对象
     * @return
     * @throws Exception
     */
    @Override
    protected boolean pick(List<String> taskIdList,//
                           List<String> enableTaskIdList,//
                           List<TaskItem> taskItemList,//
                           List<Executor> onlineExecutorList,//
                           List<Executor> onlineOwnTrafficExecutorList) throws Exception {
        // 摘取该executor的所有作业分片
        Executor targetExecutor = null;
        Iterator<Executor> iterator = onlineOwnTrafficExecutorList.iterator();
        while (iterator.hasNext()) {
            Executor executor = iterator.next();
            if (executor.getExecutorId().equals(executorId)) {
                taskItemList.addAll(executor.getTaskItemList());
                lostTraffic(executor);
                targetExecutor = executor;
                iterator.remove();
                break;
            }
        }

        if (targetExecutor == null) {
            log.warn("The executor {} maybe offline, unnecessary to extract traffic", executorId);
            return false;
        } else {
            return true;
        }
    }

    private void lostTraffic(Executor executor) {
        executor.setLostTraffic(true);
        //
        executor.setTotalLoadLevel(0);
        executor.getTaskItemList().clear();
    }
}
